import pymysql
import traceback
from bs4 import BeautifulSoup
import app
import json


import base64
import hashlib
import json
import re
import traceback

from Crypto.Cipher import AES
import requests


# 调用APP接口
def send_app_request(url, req_data):
    # 对请求数据进行加密
    diyou = EncryptUtil.get_diyou(req_data)
    xmdy = EncryptUtil.get_xmdy(diyou)
    print("diyou===", diyou)
    print("xmdy===", xmdy)

    # 发送请求
    response = requests.post(url, data={"diyou": diyou, "xmdy": xmdy})

    # 获取响应数据（密文）
    json_data = response.json()
    print("json_data==", json_data)
    response_diyou = json_data.get("diyou")
    print("response_diyou===", response_diyou)

    # 对响应数据进行解密
    decrypted_data = EncryptUtil.decrypt_data(response_diyou)
    print("decrypted_data==", decrypted_data)
    print("decrypted_data type==", type(decrypted_data))

    return json.loads(decrypted_data)







# 加解密工具类
class EncryptUtil:
    # 发送请求时，加密密码
    SEND_AES_KEY = ";3jm$>/p-ED^cVz_j~.KV&V)k9jn,UAH"
    # 发送请求时，签名密钥
    SEND_SIGN_KEY = "DY34fdgsWET@#$%wg#@4fgd345sg"
    # 接收数据时，解密密钥
    RECEIVE_AES_KEY = "54Ms5bkE6UEdyrRviJ0![OR]g+i79x]k"

    @staticmethod
    def get_diyou(data):
        # 把字典转换为JSON字符串
        if isinstance(data, dict):
            data = json.dumps(data)
        aes_encrypt_data = EncryptUtil.aes_encrypt(EncryptUtil.SEND_AES_KEY, data)
        return EncryptUtil.replace_blank(aes_encrypt_data)

    @staticmethod
    def get_xmdy(data):
        return EncryptUtil.md5value(
            EncryptUtil.SEND_SIGN_KEY + EncryptUtil.replace_blank(data) + EncryptUtil.SEND_SIGN_KEY)

    @staticmethod
    def decrypt_data(data):
        return EncryptUtil.aes_decrypt(EncryptUtil.RECEIVE_AES_KEY, data)



    @staticmethod
    def aes_encrypt(key, data):
        """
        AES加密
        :param key: 密钥
        :param data: 待加密数据
        :return: 加密后数据
        """
        data = base64.encodebytes(data.encode()).decode()
        # 替换特殊字符
        data = EncryptUtil.replace_blank(data)
        # print("data=", data)

        # 初始化加密器
        aes = AES.new(key.encode(), AES.MODE_ECB)

        # 解密
        padding_value = EncryptUtil.padding_pkcs5(data)
        encrypt_aes = aes.encrypt(padding_value)

        # 用base64转成字符串形式
        encrypted_text = base64.encodebytes(encrypt_aes).decode()
        return encrypted_text

    @staticmethod
    def aes_decrypt(key, data):
        """
        AES解密
        :param key: 密钥
        :param data: 待解密数据
        :return: 解密后数据
        """
        # 初始化加密器
        aes = AES.new(key.encode(), AES.MODE_ECB)
        # 优先逆向解密base64成bytes
        base64_decrypted = base64.decodebytes(data.encode())

        # 执行解密
        decrypted_bytes = base64.decodebytes(aes.decrypt(base64_decrypted))
        # 转换为字符串
        decrypted_text = str(decrypted_bytes, encoding="utf-8")

        # 把Unicode转成中文
        result = decrypted_text.encode().decode("unicode_escape")
        return result

    @staticmethod
    def md5value(data):
        # print("md5value data=", data)
        md5 = hashlib.md5()
        md5.update(data.encode())
        return md5.hexdigest()

    @staticmethod
    def padding_pkcs5(value):
        BS = AES.block_size
        return str.encode(value + (BS - len(value) % BS) * chr(BS - len(value) % BS))

    # 替换空字符
    @staticmethod
    def replace_blank(str_data):
        str_data = re.compile("\t|\r|\n").sub("", str_data)
        # print("replace_blank str_data=", str_data)
        return str_data


if __name__ == '__main__':
    # 加密
    send_data = {}
    content = json.dumps(send_data)
    diyou = EncryptUtil.get_diyou(content)
    print("diyou=", diyou)
    xmdy = EncryptUtil.get_xmdy(diyou)
    print("xmdy=", xmdy)




# 构造测试数据，读取JSON文件
# 参数化数据格式：[(), (), ()]
# 参数化数据格式：[[], [], []]
def build_data(file_name):
    test_data = []
    with open(app.BASE_DIR + "/data/" + file_name, encoding="UTF-8") as f:
        json_data = json.load(f)
        for case_data in json_data:
            test_data.append(tuple(case_data.values()))
    print("test_data===", test_data)
    return test_data


# keys:  num,status_code
# 方式二
def build_data_new(file_name, keys):
    key_list = keys.split(",")

    test_data = []
    with open(app.BASE_DIR + "/data/" + file_name, encoding="UTF-8") as f:
        json_data = json.load(f)
        for case_data in json_data:

            value_list = []
            for key in key_list:
                value = case_data.get(key)
                value_list.append(value)

            test_data.append(value_list)

    print("test_data===", test_data)
    return test_data


# 解析HTML，提取第三方接口需要的数据
def parse_html(html):
    soup = BeautifulSoup(html, "html.parser")
    action = soup.form.get("action")
    print("action=", action)
    form_data = {}
    for input in soup.find_all("input"):
        name = input.get("name")
        value = input.get("value")
        print(f"name={name}  value={value}")
        form_data[name] = value
    print("form_data===", form_data)
    return action, form_data


# 通用断言方法
def common_assert(test_case, response, status_code, status, description):
    test_case.assertEqual(status_code, response.status_code)
    test_case.assertEqual(status, response.json().get("status"))
    if description is not None:
        test_case.assertIn(description, response.json().get("description"))


# 数据库操作工具类
class DBUtil:
    # # 获取数据库连接
    @classmethod
    def get_conn(cls):
        return pymysql.connect(host="121.43.169.97", user="root", password="Itcast_p2p_20191228",
                               database="czbk_member",
                               port=3306, autocommit=True)

    # 关闭连接
    @classmethod
    def close_conn(cls, conn):
        if conn:
            conn.close()
            conn = None

    # 查询一条数据
    @classmethod
    def get_one(cls, sql):
        conn = None
        cursor = None
        result = None
        try:
            # 获取数据库连接
            conn = cls.get_conn()
            # 获取游标
            cursor = conn.cursor()
            # 执行SQL
            cursor.execute(sql)
            result = cursor.fetchone()
        except Exception as e:
            print("查询一条数据时出现了异常！")
            traceback.print_exc()
        finally:
            # 关闭游标
            if cursor:
                cursor.close()
            # 关闭连接
            cls.close_conn(conn)

        return result

    # 新增、修改、删除
    @classmethod
    def execute(cls, *sql):
        print("sql====", sql)
        conn = None
        cursor = None
        try:
            # 获取数据库连接
            conn = cls.get_conn()
            # 获取游标
            cursor = conn.cursor()
            # 执行SQL
            for s in sql:
                cursor.execute(s)
        except Exception as e:
            print("新增、修改、删除时出现了异常！")
            traceback.print_exc()
        finally:
            # 关闭游标
            if cursor:
                cursor.close()
            # 关闭连接
            cls.close_conn(conn)


if __name__ == '__main__':
    # r = DBUtil.get_one("select version()")
    # print(r)

    sql1 = "DELETE FROM mb_member WHERE phone='13020210002';"
    sql2 = "DELETE FROM mb_member_info WHERE member_name='13020210002';"
    sql3 = "DELETE FROM mb_member_register_log WHERE member_name='13020210002';"
    DBUtil.execute(sql1, sql2, sql3)
